﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using Lucene.Net.Analysis;
using Lucene.Net.Index;
using Lucene.Net.Documents;
using Lucene.Net.Search;
using Lucene.Net.QueryParsers;

using StandardAnalyzer = Lucene.Net.Analysis.Standard.StandardAnalyzer;

namespace OgilvyOne.Utility
{
    /// <summary>
    /// 全文搜索
    /// </summary>
    public class LuceneSearchUtil
    {
        private LuceneSearchUtil(string spath, bool create)
        {
            this.indexpath = spath + indexpath;
            this.create = create;
        }

        private string indexpath = "cn\\index";
        private bool create = false;

        public static LuceneSearchUtil GetLuceneSearchUtil(string type, string serverpath)
        {
            return new LuceneSearchUtil(serverpath, false);
        }

        public static LuceneSearchUtil GetLuecenSearchUtil(string type, string serverpath, bool create)
        {
            return new LuceneSearchUtil(serverpath, create);
        } 

        public static string GetType(string layerid)
        {
            return "cn";
        }


        protected IndexModifier CreateIndexSearch()
        {
            return new IndexModifier(GetIndexPath(), GetAnalyzer(), create);
        }

        protected virtual string GetIndexPath()
        {
            return this.indexpath;
        }

        public void AddDoc(LuceneSearchDoc doc)
        {
            IndexModifier writer = CreateIndexSearch();
            try
            {
                writer.AddDocument(GetDocument(doc));
                //writer.Optimize();
            }
            finally
            {
                if (writer != null) writer.Close();
            }

        }
        public void AddDocList(IList<LuceneSearchDoc> doclist)
        {
            IndexModifier writer = CreateIndexSearch();
            try
            {
                foreach (LuceneSearchDoc doc in doclist)
                {
                    writer.AddDocument(GetDocument(doc));
                }
                writer.Optimize();
            }
            finally
            {
                if (writer != null) writer.Close();
            }
        }

        protected Analyzer GetAnalyzer()
        {
            return new StandardAnalyzer();
        }

        protected void delete(IndexModifier modifier, string url)
        {
            Term term = new Term("url", url);  
            modifier.DeleteDocuments(term);//删除    
        }
            
        private Document GetDocument(LuceneSearchDoc doc)
        {
            Document document = new Document();
            Field FieldUrl = new Field("url", doc.Url,Field.Store.YES, Field.Index.NO);
            document.Add(FieldUrl);
            Field fieldTitle = new Field("title", doc.Ttile, Field.Store.YES, Field.Index.TOKENIZED);
            document.Add(fieldTitle);
            Field FieldContent = new Field("content", doc.Content, Field.Store.YES, Field.Index.TOKENIZED);
            document.Add(FieldContent);

            Field FieldLayerid = new Field("layerid", doc.Layerid, Field.Store.YES, Field.Index.TOKENIZED);
            document.Add(FieldLayerid);
            Field FieldColumnid = new Field("columnid", doc.Columnid, Field.Store.YES, Field.Index.NO);
            document.Add(FieldColumnid);
            return document;
        }

        public PageTools Query(string layerid, string key, int pageNo, int rows)
        {
            PageTools pt = null;
            IndexSearcher searcher = new IndexSearcher(GetIndexPath());
            BooleanQuery bquery = new BooleanQuery();
            String[] keys = new String[] { key, key };
            String[] fields = { "content", "title" };
            BooleanClause.Occur[] flags = new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD };
            Query query = MultiFieldQueryParser.Parse(keys, fields, flags, GetAnalyzer());
            bquery.Add(query, BooleanClause.Occur.MUST);
            if (layerid != null && layerid != "")
            {//分类查找
                //根据关键字构造一个数组      
                String[] ts = new String[] { layerid };
                //同时声明一个与之对应的字段数组      
                String[] fts = { "layerid" };
                //声明BooleanClause.Occur[]数组,它表示多个条件之间的关系      
                BooleanClause.Occur[] tflags = new BooleanClause.Occur[] { BooleanClause.Occur.SHOULD };
                Query query2 = MultiFieldQueryParser.Parse(ts, fts, tflags, GetAnalyzer());
                bquery.Add(query2, BooleanClause.Occur.MUST);
            }

            if (searcher != null)
            {
                
                TopDocs topDocs = searcher.Search(bquery, pageNo * rows);
               
                ScoreDoc[] docs = topDocs.scoreDocs;
                IList dataList = new ArrayList();
                for (int i = (pageNo - 1) * rows; i < docs.Length; i++)
                {
                    Document doc = searcher.Doc(docs[i].doc);
                    LuceneSearchDoc cp = new LuceneSearchDoc();
                    cp.Ttile = doc.Get("title").Replace(key, "<font color='#e48100'>" + key + "</font>");
                    
                    cp.Url = doc.Get("url");
                    cp.Content = FilterHtml(doc.Get("content"));
                    cp.Columnid = doc.Get("columnid");
                    cp.Layerid = doc.Get("layerid");
                    int ind = cp.Content.IndexOf(key);
                    String c = cp.Content;
                    if (ind > -1)
                    {
                        if (ind > 20)
                        {
                            c = cp.Content.Substring(ind - 20);
                        }
                        else
                        {
                            c = cp.Content.Substring(0);
                        }
                    }
                    
                    if (c.Length > 160)
                    {
                        c = c.Substring(0, 160) + "...";
                    }
                    c = c.Replace(key, "<font color='#e48100'>" + key + "</font>");
                    cp.Content = c;
                    dataList.Add(cp);
                }
                pt = new PageTools(dataList, pageNo, rows, topDocs.totalHits);
             }

            searcher.Close();
            return pt;
        }

        static Regex regex = new Regex("<[^<^>]+>");
        static Regex regexHand = new Regex(@"<script[\s\S]+</script*>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
        static Regex regexHand2 = new Regex("&\\w+;");
        public static string FilterHtml(string html)
        {
            
            html = regex.Replace(regexHand.Replace(html, ""), "");
            html = regexHand2.Replace(html, "");
            html = html.Replace(" ", "");
            html = html.Replace("\r\n\r\n", "").Trim();
            
            return html;
        }

        public static string Highlightkeywords(string keycontent, string k, int num) 
        {
            int start = 0;

            if (keycontent.Length < num) num = keycontent.Length - 1;
            string resultstr = keycontent; 
            if (k.Trim().IndexOf(' ') > 0) 
            { 
                string[] myArray = k.Split(' '); 

                for (int i = 0; i < myArray.Length; i++) 
                {
                    resultstr = resultstr.Replace(myArray[i].ToString(), "<font color=#e48100>" + myArray[i].ToString() + "</font>"); 
                } 

            } 
            else 
            {
                resultstr = resultstr.Replace(k, "<font color=#e48100>" + k + "</font>"); 
            }

            return resultstr; 
        }


    }
}
